package com.example.demo.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.convert.UserConvert;
import com.example.demo.dao.SysUserMapper;
import com.example.demo.dao.UserRoleMapper;
import com.example.demo.domain.app.param.AuthorizeParam;
import com.example.demo.domain.app.vo.AmountVO;
import com.example.demo.domain.app.vo.AuthorizeVO;
import com.example.demo.domain.app.vo.UserBaseVO;
import com.example.demo.domain.app.vo.UserInfoDataVO;
import com.example.demo.domain.base.PageResult;
import com.example.demo.domain.entity.SysUserCoreDO;
import com.example.demo.domain.param.UserQueryParam;
import com.example.demo.domain.param.UserUpdateParam;
import com.example.demo.domain.vo.SysDictInfoVO;
import com.example.demo.domain.vo.UserVO;
import com.example.demo.exception.BizException;
import com.example.demo.exception.ErrorConstants;
import com.example.demo.service.SysDictService;
import com.example.demo.service.UserService;
import com.example.demo.util.httpclient.HttpUtil;
import com.example.demo.util.httpclient.StringResponse;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * UserServiceImpl
 *
 * @author hao.chen
 * @time 2025/7/19 19:27
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private SysDictService sysDictService;

    @Override
    public UserVO userInfo(String userId) {
        return UserConvert.INSTANCE.doToVo(sysUserMapper.selectByUserId(userId));
    }

    /**
     * 查询所有用户
     *
     * @return 用户列表
     */
    @Override
    public PageResult<UserVO> userList(UserQueryParam param) {
        LambdaQueryWrapper<SysUserCoreDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(param.getUsername()), SysUserCoreDO::getNickname, param.getUsername());
        wrapper.eq(StringUtils.isNotBlank(param.getPhone()), SysUserCoreDO::getMobile, param.getPhone());
        Page<SysUserCoreDO> page = sysUserMapper.selectPage(new Page<>(param.getPageNum(), param.getPageSize()), wrapper);
        Page<UserVO> pageInfo = UserConvert.INSTANCE.doToVoPage(page);
        return new PageResult<>(pageInfo);
    }

    /**
     * 用户登录
     *
     * @param username 用户名
     * @param password 密码
     * @return 登录成功用户
     * @throws BizException 登录失败抛出
     */
    @Override
    public void login(String username, String password) {
        //String encrypted = CryptoUtil.sm3CalculateHash(password);
        LambdaQueryWrapper<SysUserCoreDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUserCoreDO::getMobile, username);
        wrapper.eq(SysUserCoreDO::getPassword, password);
        SysUserCoreDO users = sysUserMapper.selectOne(wrapper);
        if (Objects.isNull(users)) {
            throw new BizException(ErrorConstants.OPERATION_FAIL, "用户名或密码错误");
        }
        StpUtil.login(users.getId());
    }


    /**
     * 用户分配角色
     *
     * @param userId  用户ID
     * @param roleIds 角色ID列表
     * @return 分配成功
     * @throws BizException 分配失败抛出
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean assignRoles(Long userId, java.util.List<Long> roleIds) {
        //Example example = new Example(UserRoleDO.class);
        //example.createCriteria().andEqualTo("userId", userId);
        //userRoleMapper.deleteByExample(example);
        //int count = 0;
        //for (Long roleId : roleIds) {
        //    UserRoleDO ur = new UserRoleDO();
        //    ur.setUserId(userId);
        //    ur.setRoleId(roleId);
        //    count += userRoleMapper.insert(ur);
        //}
        //if (count != roleIds.size()) {
        //    throw new BizException(ErrorConstants.OPERATION_FAIL, "分配角色失败");
        //}
        return true;
    }

    @Override
    public void userUpdate(UserUpdateParam param) {
        SysUserCoreDO userDO = UserConvert.INSTANCE.paramToDo(param);
        sysUserMapper.updateById(userDO);
    }

    @Override
    public void create(UserUpdateParam param) {
        SysUserCoreDO userDO = UserConvert.INSTANCE.paramToDo(param);
        sysUserMapper.insert(userDO);
    }

    @Override
    public void delete(Long id) {
        sysUserMapper.deleteById(id);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public AuthorizeVO authorize(AuthorizeParam param) {
        String wechatOpenId = getWechatOpenId(param.getCode());
        SysUserCoreDO userDO = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUserCoreDO>().eq(SysUserCoreDO::getOpenidWx, wechatOpenId));
        if (Objects.isNull(userDO)) {
            String userId = generateAccount();
            userDO = new SysUserCoreDO();
            userDO.setUserId(userId);
            userDO.setOpenidWx(wechatOpenId);
            sysUserMapper.insert(userDO);
        }
        StpUtil.login(userDO.getId(), "wechat");
        AuthorizeVO authorizeVO = new AuthorizeVO();
        authorizeVO.setUid(userDO.getUserId());
        authorizeVO.setToken(StpUtil.getTokenValue());
        return authorizeVO;
    }

    @Override
    public AuthorizeVO login(@RequestBody AuthorizeParam param) {
        String wechatOpenId = getWechatOpenId(param.getCode());
        SysUserCoreDO userDO = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUserCoreDO>().eq(SysUserCoreDO::getOpenidWx, wechatOpenId));
        if (Objects.isNull(userDO)) {
            return null;
        }
        StpUtil.login(userDO.getId(), "wechat");
        AuthorizeVO authorizeVO = new AuthorizeVO();
        authorizeVO.setUid(userDO.getUserId());
        authorizeVO.setToken(StpUtil.getTokenValue());
        authorizeVO.setMobile(userDO.getMobile());
        return authorizeVO;
    }

    private String generateAccount() {
        int number = RandomUtil.randomInt(80000001, 89999999);
        if (number == 88888888) {
            return generateAccount();
        }
        String account = String.valueOf(number);
        SysUserCoreDO appUserDO = sysUserMapper.selectByUserId(account);
        if (Objects.nonNull(appUserDO)) {
            return generateAccount();
        }
        return account;
    }

    @Override
    public UserInfoDataVO detail() {
        Long userId = StpUtil.getLoginIdAsLong();
        SysUserCoreDO sysUserCoreDO = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUserCoreDO>().eq(SysUserCoreDO::getId, userId));
        UserInfoDataVO userInfoDataVO = new UserInfoDataVO();
        UserBaseVO userBaseVO = new UserBaseVO();
        userBaseVO.setId(sysUserCoreDO.getUserId());
        userBaseVO.setStatus(0);
        userBaseVO.setMobile(sysUserCoreDO.getMobile());
        userInfoDataVO.setBase(userBaseVO);
        return userInfoDataVO;
    }

    @Override
    public AmountVO amount() {
        AmountVO amountVO = new AmountVO();
        amountVO.setBalance(0.0);          // 可用余额（Double 类型）
        amountVO.setFreeze(0.0);           // 冻结金额（Double 类型）
        amountVO.setFxCommisionPaying(0.0); // 待结算分销佣金（Double 类型）
        amountVO.setGrowth(0.0);           // 成长值（Double 类型）
        amountVO.setScore(0);              // 当前可用积分（Integer 类型）
        amountVO.setScoreLastRound(0);     // 上一轮积分（Integer 类型）
        amountVO.setTotalPayAmount(0.0);   // 累计支付金额（Double 类型）
        amountVO.setTotalPayNumber(0);     // 累计支付订单数（Integer 类型）
        amountVO.setTotalRechargeAmount(0.0); // 累计充值金额（Double 类型）
        amountVO.setTotalRefundAmount(0.0);  // 累计退款金额（Double 类型）
        amountVO.setTotalScore(0);         // 累计获得积分总数（Integer 类型）
        amountVO.setTotalWithdraw(0.0);    // 累计提现金额（Double 类型）
        amountVO.setTotleConsumed(0.0);    // 累计消费金额（Double 类型）
        return amountVO;
    }

    private String getWechatOpenId(String code) {
        List<SysDictInfoVO> dictByType = sysDictService.getDictByType("wechat_config");
        String appid = dictByType.stream().filter(f -> "appid".equals(f.getCode())).map(SysDictInfoVO::getValue).findFirst().orElse(null);
        String secret = dictByType.stream().filter(f -> "secret".equals(f.getCode())).map(SysDictInfoVO::getValue).findFirst().orElse(null);
        Map<String, Object> params = Maps.newHashMap();
        String url = "https://api.weixin.qq.com/sns/jscode2session";
        params.put("appid", appid);
        params.put("secret", secret);
        params.put("js_code", code);
        params.put("grant_type", "authorization_code");
        String openId;
        try {
            StringResponse response = HttpUtil.get(url).params(params).execute();
            String content = response.getContentString();
            JSONObject resJson = JSON.parseObject(content);
            openId = resJson.getString("openid");
            log.info("微信返回数据：{}", resJson.toJSONString());
        } catch (Exception e) {
            log.error("获取微信code异常", e);
            throw new BizException(ErrorConstants.SERVER_INTERNAL_ERROR);
        }
        return openId;
    }
}
